/*!
    \file    i2c_port.c
    \brief   I2C functions port on platform for the gd30ad3x40
    
    \version 2024-10-08, V1.0.0, firmware for GD30AD3x40
*/

#include "i2c_port.h"
#include "stdio.h"

/*!
    \brief      initialize I2C GPIO
    \param[in]  none
    \param[out] none
    \retval     none
*/
void ad3x40_i2c_gpio_init()
{
    /* enable GPIOB clock */
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_AF);
    
    /* configure GPIO pins of I2C0 */
    gpio_bit_set(GPIOB,GPIO_PIN_7);//sda
    gpio_bit_set(GPIOB,GPIO_PIN_6);//sclk

    gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6|GPIO_PIN_7);

    gpio_bit_set(GPIOB,GPIO_PIN_7);//sda
    gpio_bit_set(GPIOB,GPIO_PIN_6);//sclk
    gpio_bit_reset(GPIOB,GPIO_PIN_7);//sda
    uint32_t i;
    for(i=0;i<100;i++);
    gpio_bit_set(GPIOB,GPIO_PIN_6);//sclk 0
}

/*!
    \brief      initialize I2C
    \param[in]  none
    \param[out] none
    \retval     none
*/
void ad3x40_i2c_init()
{
    /* enable GPIOB clock */
    rcu_periph_clock_enable(RCU_GPIOB);
    /* enable I2C0 clock */
    rcu_periph_clock_enable(RCU_I2C0);
    
    /* configure GPIO pins of I2C0 */
    gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6|GPIO_PIN_7);

    /* configure I2C clock */
    i2c_clock_config(I2C0,I2C0_SPEED,I2C_DTCY_2);

    /* configure I2C address */
    i2c_mode_addr_config(I2C0,I2C_I2CMODE_ENABLE,I2C_ADDFORMAT_7BITS,I2C0_SLAVE_ADDRESS7);

    /* enable I2C0 */
    i2c_enable(I2C0);

    /* enable acknowledge */
    i2c_ack_config(I2C0,I2C_ACK_ENABLE);
}

/*!
    \brief      disable I2C
    \param[in]  none
    \param[out] none
    \retval     none
*/
void ad3x40_i2c_disable()
{
    uint32_t i;
    for(i=0;i<4000;i++);
    
    rcu_periph_clock_enable(RCU_I2C0);
    i2c_disable(I2C0);
    
    exti_interrupt_flag_clear(EXTI_0);
    exti_interrupt_disable(EXTI_0);
    uint32_t j;
    for(j=0;j<4000;j++);
}

/*!
    \brief      I2C master as transmitter start
    \param[in]  none
    \param[out] none
    \retval     none
*/
void ad3x40_i2c_tx_start()
{
    /* wait until I2C bus is idle */
    while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));

    /* send a start condition to I2C bus */
    i2c_start_on_bus(I2C0);
    
    /* wait until SBSEND bit is set */
    while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));
    
    /* send slave address to I2C bus */
    i2c_master_addressing(I2C0, DUT_SLAVE_ADDRESS7_GND, I2C_TRANSMITTER);

    /* wait until ADDSEND bit is set */
    while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));
    
    /* clear the ADDSEND bit */
    i2c_flag_clear(I2C0,I2C_FLAG_ADDSEND);
}

/*!
    \brief      I2C master as transmitter transmit a byte
    \param[in]  tx_byte: The data need to be transmit 
    \param[out] none
    \retval     none
*/
void ad3x40_i2c_tx_byte(uint8_t tx_byte)
{
    /* wait until the transmit data buffer is empty */
    while(SET != i2c_flag_get(I2C0, I2C_FLAG_TBE));
    
    /* send the byte to be written */
    i2c_data_transmit(I2C0, tx_byte); 
    
    /* wait until BTC bit is set */
    while(!i2c_flag_get(I2C0, I2C_FLAG_BTC));
}

/*!
    \brief      I2C master as transmitter stop
    \param[in]  none
    \param[out] none
    \retval     none
*/
void ad3x40_i2c_tx_stop()
{
    /* send a stop condition to I2C bus */
    i2c_stop_on_bus(I2C0);
    
    /* wait until the stop condition is finished */
    while(I2C_CTL0(I2C0)&0x0200);
}

/*!
    \brief      I2C master as receiver start
    \param[in]  none
    \param[out] none
    \retval     none
*/
void ad3x40_i2c_rx_start()
{
    /* wait until I2C bus is idle */
    while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
    
    /* send a start condition to I2C bus */
    i2c_start_on_bus(I2C0);
    i2c_ack_config(I2C0,I2C_ACK_ENABLE);
    
    /* wait until SBSEND bit is set */
    while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));
    
    /* send slave address to I2C bus */
    i2c_master_addressing(I2C0, DUT_SLAVE_ADDRESS7_GND, I2C_RECEIVER);
    
    /* wait until ADDSEND bit is set */
    while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));
    
    /* clear the ADDSEND bit */
    i2c_flag_clear(I2C0,I2C_FLAG_ADDSEND);
}

/*!
    \brief      I2C master as receiver receive a byte
    \param[in]  none
    \param[out] none
    \retval     rx_byte
*/
uint8_t ad3x40_i2c_rx_byte()
{    
    /* wait until the receive data buffer is not empty */
    while(SET != i2c_flag_get(I2C0, I2C_FLAG_RBNE));
    
    /* read a byte from the slave */
    uint8_t rx_byte = i2c_data_receive(I2C0);
    
    /* disable acknowledge */
    i2c_ack_config(I2C0,I2C_ACK_DISABLE);
    
    return rx_byte;
}

/*!
    \brief      I2C master as receiver receive a byte ack
    \param[in]  none
    \param[out] none
    \retval     rx_byte
*/
uint8_t ad3x40_i2c_rx_byte_ack()
{    
    /* wait until the receive data buffer is not empty */
    while(SET != i2c_flag_get(I2C0, I2C_FLAG_RBNE));
    
    /* read a byte from the slave */
    uint8_t rx_byte = i2c_data_receive(I2C0);

    /* disable acknowledge */
    i2c_ack_config(I2C0,I2C_ACK_ENABLE);
    
    return rx_byte;
}

/*!
    \brief      I2C master as receiver stop
    \param[in]  none
    \param[out] none
    \retval     none
*/
void ad3x40_i2c_rx_stop()
{
    /* send a stop condition to I2C bus */
    i2c_stop_on_bus(I2C0);
    
    /* wait until the stop condition is finished */
    while(I2C_CTL0(I2C0)&0x0200);
}

